package linestrategy

import (
	"codejy/analysis"
	"codejy/analysis/codeanalysis"
	"codejy/analysis/lineanalysis"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"strconv"
	"strings"
)

// 定义策略
type ForStrategy struct {
}

// 注册策略
func init() {
	RegisterStrategy(&ForStrategy{})
}

// 判断
func (f *ForStrategy) getId() int {
	return lineanalysis.For
}
func (f *ForStrategy) Execute(threadStore *structdef.ThreadStore) {
	ForHandle(threadStore)
}

func ForHandle(threadStore *structdef.ThreadStore) {
	codes := threadStore.Codes
	currentPointer := threadStore.CurrentPoint
	length := len(codes)
	for i := currentPointer; i < length; i++ {
		code := codes[i]
		end := GetForCodeBlockAllEnd(codes, i+1)
		//判断是否是无限循环
		if analysis.IsForInfiniteLoop(code.LineContent) {
			for {
				LineExecute(threadStore, i+1, end)
				if threadStore.BreakFlag {
					threadStore.CurrentPoint = end //指针结束
					threadStore.BreakFlag = false  //恢复默认值
					return
				}
			}
		}

		//判断是否是for 0..10 -> i { }循环
		if analysis.IsForNumberLoop(code.LineContent) {
			//截取for i循环的条件表达式
			forContent := code.LineContent[3:]
			//去掉结尾的{
			forContent = strings.ReplaceAll(forContent, "{", "")
			//按照in分割,获取第一个->前面的内容
			firstContent := forContent[:strings.Index(forContent, "->")]
			index := strings.Index(firstContent, "..")
			//按照..分割,获取第一个..前面的内容
			firstContent1 := firstContent[:index]
			atoi1, err := strconv.Atoi(firstContent1)
			if err != nil {
				panic("for a..b -> i { }循环 a..b必须是整数")
			}
			//按照..分割,获取第二个..后面的内容
			secondContent1 := firstContent[index+2:]
			atoi2, err := strconv.Atoi(secondContent1)
			if err != nil {
				panic("for a..b -> i { }循环 a..b必须是整数")
			}
			//获取->后面的内容
			secondContent := forContent[strings.Index(forContent, "->")+2:]

			store.RegisterVariable(threadStore, structdef.NewVarDefinitionValue(secondContent, "0", codeanalysis.NUM))
			//写一个有限循环
			for i1 := atoi1; i1 < atoi2; i1++ {
				LineExecute(threadStore, i+1, end)
				if threadStore.BreakFlag {
					threadStore.CurrentPoint = end //指针结束
					threadStore.BreakFlag = false  //恢复默认值
					return
				}
				//判断是否是to
				if threadStore.ReturnFlag {
					threadStore.CurrentPoint = end //指针结束
					return
				}
				if threadStore.ContinueFlag {
					threadStore.ContinueFlag = false //恢复默认值
				}
				store.ModifyVariable(threadStore, structdef.NewVarDefinitionValue(secondContent, strconv.Itoa(i1), codeanalysis.NUM))
			}
			//结束循环
			threadStore.CurrentPoint = end //指针结束
			return
		}

		//判断是否是in循环
		if analysis.IsForInLoop(code.LineContent) {
			//截取for i循环的条件表达式
			forContent := code.LineContent[3:]
			//去掉结尾的{
			forContent = strings.ReplaceAll(forContent, "{", "")
			//按照->分割,获取第一个->前面的内容
			firstContent := forContent[:strings.Index(forContent, "->")]

			//判断第1个必须是实例变量类型
			if codeanalysis.IsInstanceVariable(threadStore, firstContent) == -1 {
				panic("for in循环的第二个参数必须是实例变量")
			}
			//获取实例变量的值
			variable, b := store.GetVariable(threadStore, firstContent)
			if !b {
				panic("实例变量" + firstContent + "不存在")
			}

			//获取第一个->后面的内容
			secondContent := forContent[strings.Index(forContent, "->")+2:]
			//判断secondContent是否存在逗号
			index := strings.Index(secondContent, ",")
			var kName string
			var vName string
			if index == -1 {
				panic("for xx -> xx { } 循环的第二个参数必须是key,value,或者i,value")
			} else {
				kName = secondContent[:index]
				vName = secondContent[index+1:]
			}
			//获取实例中内存函数next
			prop, _ := store.GetInstanceProp(threadStore, variable.Value)
			typeName, _ := prop["@TYPENAME@"]  //获取实例的类型名称
			scope, _ := prop["@TYPEFILEPATH@"] //获取实例的类型名称
			typeDefinition := store.GetTypeDefinition(scope.Value, typeName.Value)
			//获取next方法
			nextMethod, p := typeDefinition.Methods["next"]
			if !p {
				panic("实例" + firstContent + "不存在next方法,无法进行for in循环")
			}
			for {
				value1 := store.NweStatusRestore(threadStore, func() string {
					threadStore.CurrentInstanceAddress = variable.Value
					//调用next方法
					globalfunc.ExecuteFunc("ExecuteTypeMethod", threadStore, "next", nextMethod, []string{}) //执行方法
					//获取函数返回值
					variable1, p1 := store.GetVariable(threadStore, "next")
					if !p1 {
						panic("实例" + firstContent + "的next方法没有返回值,无法进行for in循环")
					}
					if variable1.Value == `""` { //如果返回值为空,表示next方法没有返回值,跳出循环
						return ""
					}
					//如果是字符串,那么就去掉""
					if strings.HasPrefix(variable1.Value, "\"") && strings.HasSuffix(variable1.Value, "\"") {
						variable1.Value = variable1.Value[1 : len(variable1.Value)-1]
					}
					//判断返回值是否存在逗号
					index1 := strings.Index(variable1.Value, ",")
					var kNameV string
					var vNameV string
					if index1 == -1 {
						panic("实例" + firstContent + "的next方法返回值必须是key,value,或者i,value")
					} else {
						kNameV = variable1.Value[:index1]
						vNameV = variable1.Value[index1+1:]
					}

					split := strings.Split(variable1.Value, ",")
					var variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, split[0]).(int)
					store.CreateAndModifyVariable(threadStore, structdef.NewVarDefinitionValue(kName, kNameV, variableType))
					variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, split[1]).(int)
					store.CreateAndModifyVariable(threadStore, structdef.NewVarDefinitionValue(vName, vNameV, variableType))
					return variable1.Value
				})
				//如果返回是空,那么就跳出循环,表示没有下一个值了
				if value1 == "" {
					threadStore.CurrentPoint = end //指针结束
					return
				}
				//执行for循环内部代码
				LineExecute(threadStore, i+1, end)
				if threadStore.BreakFlag {
					threadStore.CurrentPoint = end //指针结束
					threadStore.BreakFlag = false  //恢复默认值
					return
				}
				//判断是否是to
				if threadStore.ReturnFlag {
					threadStore.CurrentPoint = end //指针结束
					return
				}
				if threadStore.ContinueFlag {
					threadStore.ContinueFlag = false //恢复默认值
				}
			}

		}
		//判断是否是for i循环
		if analysis.IsForLoop(code.LineContent) {
			//截取for i循环的条件表达式
			forContent := code.LineContent[3:]
			//获取第一个;的位置
			firstIndex := strings.Index(forContent, ";")
			//截取变量名
			varName := forContent[:strings.Index(forContent, "=")]
			//获取第二个;的位置
			secondIndex := strings.LastIndex(forContent, ";")
			//获取第一个;前面的内容
			firstContent := forContent[:firstIndex]
			//获取第二个;前面的内容
			secondContent := forContent[firstIndex+1 : secondIndex]
			//获取第二个;后面的内容
			thirdContent := forContent[secondIndex+1:]
			//排除第二个;后面的{
			thirdContent = strings.ReplaceAll(thirdContent, "{", "")
			//1.注册变量  2.计算第一个;
			expression := firstContent[strings.Index(firstContent, "=")+1:] //获取=号后面的内容
			value := globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, expression).(string)
			var variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, value).(int)
			//必须是数值类型
			if variableType != codeanalysis.NUM {
				panic("for ?;?;? 第一个?必须是数值类型")
			}
			store.RegisterVariable(threadStore, structdef.NewVarDefinitionValue(varName, value, variableType))

			for {
				//计算第二个;前面的内容
				secondContent1 := globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, secondContent).(string)
				variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, secondContent1).(int) //获取类型
				//必须是数值布尔类型
				if variableType != codeanalysis.BOOL {
					panic("for ?;?;? 第二个?必须是布尔类型")
				}
				//判断第二个;前面的内容是否为真,如果为真就执行循环体
				if secondContent1 == "true" {
					LineExecute(threadStore, i+1, end)
					if threadStore.BreakFlag {
						threadStore.CurrentPoint = end //指针结束
						threadStore.BreakFlag = false  //恢复默认值
						return
					}
					//判断是否是to
					if threadStore.ReturnFlag {
						threadStore.CurrentPoint = end //指针结束
						return
					}
					if threadStore.ContinueFlag {
						threadStore.ContinueFlag = false //恢复默认值
					}
					//计算第二个;后面的内容
					expression1 := globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, thirdContent).(string)
					//赋值给变量
					variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, expression1).(int)
					//必须是数值类型
					if variableType != codeanalysis.NUM {
						panic("for?;?;? 第三个?必须是数值类型(整数或者浮点数)")
					}
					store.ModifyVariable(threadStore, structdef.NewVarDefinitionValue(varName, expression1, variableType))
				} else {
					//结束循环
					threadStore.CurrentPoint = end //指针结束
					return
				}

			}
		}

		//判断是否条件循环 for { }
		if analysis.IsForConditionLoop(code.LineContent) {
			//截取for i循环的条件表达式
			forContent := code.LineContent[3:]
			//去掉结尾的{
			forContent = strings.ReplaceAll(forContent, "{", "")
			for {
				//计算条件表达式
				value := globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, forContent).(string)
				var variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, value).(int)
				//必须是数值布尔类型
				if variableType != codeanalysis.BOOL {
					panic("for循环迭代变量必须是数值类型(整数或者浮点数) ,不然你循环个啥呢?")
				}
				if value == "true" {
					LineExecute(threadStore, i+1, end)
					if threadStore.BreakFlag {
						threadStore.CurrentPoint = end //指针结束
						threadStore.BreakFlag = false  //恢复默认值
						return
					}
					//判断是否是to
					if threadStore.ReturnFlag {
						threadStore.CurrentPoint = end //指针结束
						return
					}
					if threadStore.ContinueFlag {
						threadStore.ContinueFlag = false //恢复默认值
					}
				} else {
					//结束循环
					threadStore.CurrentPoint = end //指针结束
					return
				}
			}
		}

	}
}

// 获取最后一个}的位置
func GetForCodeBlockAllEnd(codeBlocks []structdef.LineCodeDefinition, startIndex int) int {
	length := len(codeBlocks)
	var ifNum = 1
	var j int
	for j = startIndex; j < length; j++ {
		ifBlockCode := codeBlocks[j]
		lineContent := ifBlockCode.LineContent
		//截取if语句块的内容
		if strings.HasPrefix(lineContent, "}") {
			ifNum--
		}
		if ifNum == 0 {
			//判断是否有for语句块
			if analysis.IsFor(codeBlocks[j].LineContent) {
				//如果有for语句块就继续往下找
				ifNum++
				continue
			}
			break
		}
		if strings.HasSuffix(lineContent, "{") {
			ifNum++
		}
	}
	return j
}
